/***********************************************
 This file is part of redia-bapps-main-ios.
 
 Copyright (c) 2015 Redia A/S
 
 Redia-bapps-main-ios is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
 
 Redia-bapps-main-ios is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with redia-bapps-main-ios.  If not, see <http://www.gnu.org/licenses/>.
 
 *********************************************** */

//
//  BASearchResultsColumnViewController.m
//  redia-bapps-ios
//
//  Created by Nikolaj Tørring on 27/10/13.
//  Copyright (c) 2013 redia. All rights reserved.
//

#import "BASearchResultsColumnViewController.h"
#import "BALibrarySettings.h"
#import "BACollection.h"
#import "BARecord.h"
#import "BACoverUrlAndAvailabilityMemoryCache.h"
#import "BASearchResultCell.h"
#import "BALoadingIndicatorCell.h"
#import "LazyLoadManager.h"
#import "InfoGalleriImageUrlUtils.h"
#import "BAMaterialViewController.h"
#import "BASlideInViewController.h"
#import "BATerm.h"
#import "BAFacet.h"
#import "BARootViewController.h"
#import "BAPatronSettings.h"

#ifdef BA_LIBRARIAN_BUILD
#import "LBRPCManager.h"
#endif

#ifdef BA_IMF_BUILD
#import "IMFPackageEditManager.h"
#endif


@interface BASearchResultsColumnViewController (){
    NSMutableSet* currentImageLoaders;
    NSInteger searchOffset;
    BOOL isSearching;
    //NSMutableArray* filterDescriptionsBarButtons;
    //NSMutableArray* filterDescriptionStrings;
    BOOL isLibrarianAlmaSearchMore;

}
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (weak, nonatomic) IBOutlet UIImageView *materialTypeImageView;
@property (weak, nonatomic) IBOutlet UIView *materialIconBackground;
@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *loadingIndicator;

@property (nonatomic, strong) NSMutableArray* searchRecords;
@property (nonatomic, strong) BASearchResult* latestResult;

//@property (weak, nonatomic) IBOutlet UIScrollView *filterDescriptionsScroller; // DEPRECATED
//@property (weak, nonatomic) IBOutlet UIImageView *filterDescriptionsSelectionIndicatorImage; //FIXME: DEP
//@property (strong, nonatomic) IBOutlet UIView *filterDescriptionsContent; //FIXME: DEP
//@property (weak, nonatomic) IBOutlet NSLayoutConstraint *filterDescriptionsContentWidth; //FIXME: DEP

@property (nonatomic) BOOL loadResultsStarted;

@end

@implementation BASearchResultsColumnViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];


    if (self.searchQueryFilter == nil) {
        self.searchQueryFilter = @{};
    }
    
    
    if (RD_IS_IPAD) {
        [self.tableView registerNib:[UINib nibWithNibName:@"BASearchResultCell_iPad" bundle:nil] forCellReuseIdentifier:@"SearchResultCellNormal"];
        [self.tableView registerNib:[UINib nibWithNibName:@"BASearchResultCell_iPad" bundle:nil] forCellReuseIdentifier:@"SearchResultCellExpanded"];
    } else {
        [self.tableView registerNib:[UINib nibWithNibName:@"BASearchResultCell_iPhone" bundle:nil] forCellReuseIdentifier:@"SearchResultCellNormal"];
        [self.tableView registerNib:[UINib nibWithNibName:@"BASearchResultCell_iPhone" bundle:nil] forCellReuseIdentifier:@"SearchResultCellExpanded"];
    }
    
    [self updateMaterialType];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadTableWithNotification:) name:BA_COVER_URL_CACHE_IMAGE_LOADED object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNewCoverUrls:) name:BA_COVER_URL_CACHE_COVER_URLS_ARRIVED object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadTableWithNotification:) name:BA_AVAILAIBILITY_CACHE_AVAILABILITIES_ARRIVED object:nil];

}

-(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    [self.tableView reloadData];
}

- (void)dealloc
{
    [BARPCManager closeConnectionsForView:self];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:BA_COVER_URL_CACHE_IMAGE_LOADED object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:BA_COVER_URL_CACHE_COVER_URLS_ARRIVED object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:BA_AVAILAIBILITY_CACHE_AVAILABILITIES_ARRIVED object:nil];
    
}

-(void)cancelAllRPCConnections
{
    [BARPCManager closeConnectionsForView:self];
}


-(void)reloadTableWithNotification:(id)sender
{
    [self.tableView reloadData];
}

-(void)handleNewCoverUrls:(id)sender
{
    NSArray* visibleCells = [self.tableView visibleCells];
    NSMutableArray* visibleIdentifiers = [NSMutableArray new];
    
    for (BASearchResultCell* cell in visibleCells) {
        if ([cell isKindOfClass:[BASearchResultCell class]]) {
            if (cell.record && [cell.record.identifier length]>0) {
                [visibleIdentifiers addObject:cell.record.identifier];
            }
        }
    }
    [[BACoverUrlAndAvailabilityMemoryCache instance] fetchCoverImagesForIdentifiers:visibleIdentifiers];
}


- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(void)updateMaterialType{
    if (self.isViewLoaded) {
        BALibrarySettings* libsettings = [BALibrarySettings instance];
        NSArray* materialType = [self.searchQueryFilter objectForKey:[libsettings getDefaultMaterialTypeFilter]];
        if (materialType == nil) {
            [self.materialTypeLabel setText:@"Alle"];
            self.materialTypeImageView.image = [libsettings getIconForMaterialType:@"Alle"
                                                                 contextIdentifier:BATypeIconContextIPadSearchColumnHeader
                                                                             color:[libsettings getCustomerColorDark]]; //FIXME: not used now
        } else{
            NSString* typetext = materialType.firstObject;
            if ([typetext length]>=1) {
                typetext = [typetext stringByReplacingCharactersInRange:NSMakeRange(0,1) withString:[[typetext substringToIndex:1] uppercaseString]];
            }
            [self.materialTypeLabel setText:typetext];
            self.materialTypeImageView.image = [libsettings getIconForMaterialType:typetext
                                                                 contextIdentifier:BATypeIconContextIPadSearchColumnHeader
                                                                             color:[libsettings getCustomerColorDark]];
        }
    }
    
}

-(void)externalPerformAlmaSearchWithSearchString:(NSString*)searchString
{
    [self view];
    isLibrarianAlmaSearchMore=YES;
    self.searchQuery = searchString;
    [self loadResults];
}

-(void)setSearchQueryFilter:(NSDictionary *)searchQueryFilter{
    _searchQueryFilter = searchQueryFilter;
    if (self.searchQuery.length > 0) {
        [self.tableView setHidden:YES];
        searchOffset = 0;
        //[self.loadingIndicator startAnimating];
        //[self loadResults];
    }
    [self updateMaterialType];
}

-(void)loadResults{
    if (self.searchQuery != nil) {
        _loadResultsStarted = YES;
        if (searchOffset==0) {
            [self.tableView setContentOffset:CGPointZero animated:NO];
            [self.loadingIndicator startAnimating];
        }
        [BARPCManager closeConnectionsForView:self];
        isSearching = YES;
        
        if (!isLibrarianAlmaSearchMore) {
            [BARPCManager searchAsyncFromView:self
                                        query:self.searchQuery
                                       filter:self.searchQueryFilter
                                        count:20
                                       offset:searchOffset
                                  resultBlock:^(BASearchResult *result) {
                                      [self showSearchResultsWithResults:result isFirstPage:(searchOffset==0)];
                                      if (self.searchResultDelegate!=nil) {
                                          [self.searchResultDelegate searchResultsColumnViewController:self updatedWithSearchResult:result];
                                      }
                                      searchOffset+=20;
                                      isSearching = NO;
                                  }
                                   errorBlock:^(int code, NSString *error) {
                                       DLog(@"search error: %@",error);
                                       //FIXME: what to do about loading more results?
                                       isSearching = NO;
                                   }
             ];
        } else {
            
#ifdef BA_LIBRARIAN_BUILD
            [LBRPCManager librarianSearchAsyncFromView:self
                                                 query:self.searchQuery
                                                 count:20
                                                offset:searchOffset
                                           resultBlock:^(BASearchResult *result) {
                                               [self showSearchResultsWithResults:result isFirstPage:(searchOffset==0)];
                                               if (self.searchResultDelegate!=nil) {
                                                   [self.searchResultDelegate searchResultsColumnViewController:self updatedWithSearchResult:result];
                                               }
                                               searchOffset+=20;
                                               isSearching = NO;
                                           }
                                            errorBlock:^(int errorCode, NSString *errorMessage) {
                                                DLog(@"search error: %@",errorMessage);
                                                //FIXME: what to do about loading more results?
                                                isSearching = NO;
                                            }
             ];
#endif
        }
        
    }
    
}


-(void)setSearchQuery:(NSString *)searchQuery{
    _searchQuery = searchQuery;
    
    [self clearFilterButtons];
    
    [self.tableView setHidden:YES];
    if (searchQuery.length > 0) {
        //By setting the SearchQueryFilter we initiate a new search!
        [self setSearchQueryFilter:@{}];
        
        searchOffset = 0;
        //[self.loadingIndicator startAnimating];
        //[self loadResults];
    }
    
}

-(void)clearFilterButtons
{
    /* FIXME: to be removed
    [self.filterDescriptionsContent setHidden:YES];
    for (UIButton* b in filterDescriptionsBarButtons) {
        [b removeFromSuperview];
    }
    filterDescriptionsBarButtons = nil;
    filterDescriptionStrings = nil;
    [filterDescriptionsBarButtons removeAllObjects];
    [self.filterDescriptionsScroller setContentOffset:CGPointZero animated:NO];
     */
}


-(void)showSearchResultsWithResults:(BASearchResult*)result isFirstPage:(BOOL)isFirstPage{
    
    [self.loadingIndicator stopAnimating];
    [self.tableView setHidden:NO];
    self.latestResult = result;
    
    
    NSMutableArray* records = [NSMutableArray new];
    
    for (BACollection* collection in result.data) {
        for (BARecord* record in collection.records) {
            [records addObject:record];
        }
    }
    
    if (result.count == 0) {
        DLog(@"No result!");
    } else {
        [self fetchAvailabilityForSearchResults:records];
        [self fetchCoverUrlsForSearchResults:records];
        
        
    }
    
    
    
    if (isFirstPage) {
        self.searchRecords = records;
    } else{
        [self.searchRecords addObjectsFromArray:records];
    }
    [self.tableView reloadData];
}


-(void)fetchAvailabilityForSearchResults:(NSArray*)records
{
    NSMutableArray* identifiers = [NSMutableArray new];
    
    for (BARecord* record in records) {
        [identifiers addObject:record.identifier];
    }
    
    [BARPCManager getAvailabilityAsyncFromView:self
                                   identifiers:identifiers
                            includeHoldingInfo:NO
                                   resultBlock:^(NSDictionary *result) {
                                       [self appendAvailabilityRecords:result];
                                   }
                                    errorBlock:^(int errorCode, NSString *errorMessage) {
                                        DLog(@"error fetching availability %d %@",errorCode, errorMessage);
                                    }];
    
    
}

-(void)fetchCoverUrlsForSearchResults:(NSArray*)records
{
    NSMutableArray* identifiers = [NSMutableArray new];
    
    for (BARecord* record in records) {
        [identifiers addObject:record.identifier];
    }
    
    [[BACoverUrlAndAvailabilityMemoryCache instance] fetchCoverUrlsForIdentifiers:identifiers];
    
    /* old code
    [BARPCManager getCoverUrlsAsyncFromView:self
                            coverUrlQueries:identifiers
                                resultBlock:^(NSDictionary* result) {
                                    [self appendCoverUrls:result];
                                }
                                 errorBlock:^(int errorCode, NSString *errorMessage) {
                                     DLog(@"error fetching coverurls %d %@",errorCode, errorMessage);
                                 }];
     
     */
    
}

-(void)appendAvailabilityRecords:(NSDictionary *)availabilities
{
    [[BACoverUrlAndAvailabilityMemoryCache instance] appendAvailabilityRecords:availabilities];
    
    [self.tableView reloadData];
}

-(void)appendCoverUrls:(NSDictionary *)coverUrls
{
    [[BACoverUrlAndAvailabilityMemoryCache instance] appendCoverUrls:coverUrls];
    
    [self.tableView reloadData];
}

/*
-(CGFloat)createNewFilterDescriptionButtonWithTerm:(NSString*)term count:(int)count isSelected:(BOOL)isSelected atX:(CGFloat)cur_x
{
    UIButton* newbutton = [UIButton buttonWithType:UIButtonTypeCustom];
    if (isSelected) {
        [newbutton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
        [newbutton setTitleColor:[UIColor grayColor] forState:UIControlStateHighlighted];
    } else {
        [newbutton setTitleColor:[[UIColor whiteColor] colorWithAlphaComponent:0.40] forState:UIControlStateNormal];
        [newbutton setTitleColor:[[UIColor grayColor] colorWithAlphaComponent:0.40] forState:UIControlStateHighlighted];
    }
    NSString* titletext = [term uppercaseString]; //[[NSString stringWithFormat:@"%@ (%d)",term, count] uppercaseString];
    [newbutton setTitle:titletext forState:UIControlStateNormal];
    if (isSelected ) {
        [newbutton.titleLabel setFont:BA_FONT_REGULAR(13)];
    } else {
        [newbutton.titleLabel setFont:BA_FONT_LIGHT(13)];
    }
    
    CGSize textrect = [titletext sizeWithFont:newbutton.titleLabel.font];
    CGFloat buttonWidth = textrect.width + 10;
    newbutton.frame = CGRectMake(cur_x, 3, buttonWidth, 30);
    [self.filterDescriptionsContent addSubview:newbutton];
    [newbutton addTarget:self action:@selector(filterButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
    
    [filterDescriptionsBarButtons addObject:newbutton];
    
    return buttonWidth;
}


-(void)selectFilterButton:(UIButton*)sel_button
{
    [sel_button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [sel_button setTitleColor:[UIColor grayColor] forState:UIControlStateHighlighted];
    [sel_button.titleLabel setFont:BA_FONT_REGULAR(13)];
    
    CGRect sel_rect = sel_button.frame;
    CGFloat mid_x = sel_rect.origin.x + sel_rect.size.width/2.0;
    CGRect indicator_rect = self.filterDescriptionsSelectionIndicatorImage.frame;
    CGFloat indicator_width = indicator_rect.size.width;
    indicator_rect.origin.x = mid_x - indicator_width/2.0;
    
    [UIView animateWithDuration:0.5 animations:^{
        self.filterDescriptionsSelectionIndicatorImage.frame = indicator_rect;
    }];
    
    //FIXME: DEP: [self.filterDescriptionsScroller scrollRectToVisible:sel_rect animated:YES];
    
    
    for (UIButton* otherbutton in filterDescriptionsBarButtons) {
        if (otherbutton!=sel_button) {
            [otherbutton setTitleColor:[[UIColor whiteColor] colorWithAlphaComponent:0.40] forState:UIControlStateNormal];
            [otherbutton setTitleColor:[[UIColor grayColor] colorWithAlphaComponent:0.40] forState:UIControlStateHighlighted];
            [otherbutton.titleLabel setFont:BA_FONT_LIGHT(13)];
            
        }
    }
}

-(IBAction)filterButtonClicked:(id)sender
{
    
    NSUInteger button_index = [filterDescriptionsBarButtons indexOfObject:sender];
    if (button_index!=NSNotFound && button_index<[filterDescriptionStrings count] && button_index<[filterDescriptionsBarButtons count]) {
        NSString* filtertext = [filterDescriptionStrings objectAtIndex:button_index];
        [self selectFilterButton:[filterDescriptionsBarButtons objectAtIndex:button_index]];
        
        if ([filtertext length]>0) {
            self.searchQueryFilter = @{[[BALibrarySettings instance] getDefaultMaterialTypeFilter]: @[filtertext]};
        } else {
            self.searchQueryFilter = @{}; //make a default "all" search
        }
        
    }
    
}
 */

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    if (self.searchRecords.count > 0) {
        if (self.latestResult.more) {
            return 2;
        }
        else{
            return 1;
        }
    }
    return 0;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (section == 0) {
        return self.searchRecords.count;
    } else{
        return 1;
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.section == 0) {
        BOOL isExpanded = [self shouldCellBeExpandedForIndexPath:indexPath];
        BASearchResultCell* cell = nil;
        if (isExpanded) {
            cell = [tableView dequeueReusableCellWithIdentifier:@"SearchResultCellExpanded"];
        } else{
            cell = [tableView dequeueReusableCellWithIdentifier:@"SearchResultCellNormal"];
        }
        
        cell.isShowingMoreView = isExpanded; //must be called before setRecord
        
        BARecord* record = [self.searchRecords objectAtIndex:indexPath.row];
        [cell setRecord:record];
        
        BACoverUrlAndAvailabilityMemoryCache* cache = [BACoverUrlAndAvailabilityMemoryCache instance];
        
        BAAvailability* availabilityInfo = [cache getAvailabilityForIdentifier:record.identifier];
        if (availabilityInfo) {
            [cell setAvailability:availabilityInfo];
        }
        
        [cache fetchCoverImagesForIdentifiers:@[record.identifier]];
        //dep: handled by caching: [cell fetchCoverImage];

        return cell;
    }
    else{
        BALoadingIndicatorCell* cell = [tableView dequeueReusableCellWithIdentifier:@"LoadingIndicatorCell"];
        if(cell == nil){
            cell = [[[NSBundle mainBundle] loadNibNamed:@"BALoadingIndicatorCell" owner:self options:nil] objectAtIndex:0];
        }
        
        [cell.loadingIndicator startAnimating];
        
        return cell;
    }
    
}

-(BOOL)shouldCellBeExpandedForIndexPath:(NSIndexPath *)indexPath
{
    
    BARecord* record =  [self.searchRecords objectAtIndex:indexPath.row];
    BAPatronSettings* patronsettings = [BAPatronSettings instance];
    BOOL isExpanded = (record.moreInSameSeries && [patronsettings isUserAllowedLibrarianAccessForCurrentLibrary]) || [patronsettings isUserAllowedIMFEditorAccessForCurrentLibrary];
    
    return isExpanded;
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    if (indexPath.section == 1) {
        return 44;
    }
    
    BOOL isExpanded = [self shouldCellBeExpandedForIndexPath:indexPath];
    
    //DLog(@"idx %d expanded %d",indexPath.row,isExpanded);
    
    if (RD_IS_IPAD) {
        if (isExpanded) {
            return BA_SEARCH_RESULT_CELL_EXPANDED_HEIGHT_IPAD;
        } else {
            return BA_SEARCH_RESULT_CELL_DEFAULT_HEIGHT_IPAD;
        }
    } else {
        //iphone
        if (isExpanded) {
            return BA_SEARCH_RESULT_CELL_EXPANDED_HEIGHT_IPHONE;
        } else {
            return BA_SEARCH_RESULT_CELL_DEFAULT_HEIGHT_IPHONE;
        }
    }
    
}



#pragma mark - Table view delegate
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    BARecord* rec = [self.searchRecords objectAtIndex:indexPath.row];
    
    BASlideInViewController *slideIn = [BASlideInViewController findSlideInViewController:self];
    
    
    if (slideIn != nil && rec != nil) {
        UIViewController<BAMaterialViewControllerProtocol>* mvc = [[BARootViewController instance] createMaterialViewController]; // [BAMaterialViewController new];
        [slideIn slideInViewController:mvc animated:YES completion:nil];
        
        BACoverUrlAndAvailabilityMemoryCache* cache = [BACoverUrlAndAvailabilityMemoryCache instance];
        
        BACoverUrl* cu_object = [cache getCoverUrlForIdentifier:rec.identifier];
        BAAvailability* availability = [cache getAvailabilityForIdentifier:rec.identifier];
        UIImage* currentImage = [cache getSearchResultCellSizedCoverImageForIdentifier:rec.identifier];
        
        [mvc showRecord:rec withCoverUrl:cu_object.url currentImage:currentImage availability:availability];
        
    }
}



#pragma mark UIScrollViewDelegate

- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    CGFloat actualPosition = scrollView.contentOffset.y;
    CGFloat contentHeight = scrollView.contentSize.height-scrollView.frame.size.height;
    if (!isSearching && actualPosition >= contentHeight && self.latestResult.more) {
        isSearching = YES;
        [self loadResults];
    }
}



@end
